package cybercode.carsaleserver.controller.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import cybercode.carsaleserver.config.redis.LettuceUtil;
import cybercode.carsaleserver.constant.Values;
import cybercode.carsaleserver.dto.R;
import cybercode.carsaleserver.dto.ResultCode;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;

// Class: TokenInterceptor, 来源于: user, 最后更新时间: 2022-10-26 10:10
@Component
@Log4j2
public class TokenInterceptor implements HandlerInterceptor {

    @Value("${cross-origin.enable}")
    private boolean enableCross;

    @Value("${cross-origin.prod}")
    private String prodUrl;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

//        String feignTag = request.getHeader(FeignRequestInterceptor.TAG);
//
//        //openfeign访问，不做验证
//        if(null != feignTag && feignTag.equals(FeignRequestInterceptor.TAG_KEY)){
//            return HandlerInterceptor.super.preHandle(request, response, handler);
//        }

        String token = request.getHeader("Authorization");// 从 http 请求头中取出 token

        //不是类或方法，放行
        if (!(handler instanceof HandlerMethod)) {
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }

        boolean reqAllowed;

        //获取处理方法
        HandlerMethod handlerMethod = (HandlerMethod) handler;

        //获取方法的注解
        Method method = handlerMethod.getMethod();
        boolean methodAnnoExist = method.isAnnotationPresent(TokenVerify.class);


        //方法注解存在时优先
        if (methodAnnoExist) {
            //获取方法注解
            if (method.getAnnotation(TokenVerify.class).required()) {
                //该方法需要验证token
                reqAllowed = checkToken(token);
            } else {
                reqAllowed = true;
            }

        } else {
            //仅当方法注解不存在时才去读取类注解
            //获取类注解
            Class<?> beanType = handlerMethod.getBeanType();
            if (beanType.isAnnotationPresent(TokenVerify.class) && beanType.getAnnotation(TokenVerify.class).required()) {
                //该类需要验证token。
                reqAllowed = checkToken(token);
            } else {
                //无需验证token
                reqAllowed = true;
            }
        }

        if (reqAllowed) {
            return HandlerInterceptor.super.preHandle(request, response, handler);
        } else {
            response.reset();
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            if (!enableCross) {
                response.setHeader("Access-Control-Allow-Origin", prodUrl);
            } else {
                response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            }

//            response.setHeader("Access-Control-Allow-Credentials", "true");
            PrintWriter pw = response.getWriter();


            ObjectMapper om = new ObjectMapper();

            pw.print(om.writeValueAsString(R.fail(ResultCode.UN_AUTHORIZED)));
            pw.flush();
            pw.close();
            return false;
        }

    }

    /**
     * 验证token是否存在于redis中
     *
     * @param token
     * @return
     */
    private boolean checkToken(String token) {
//        log.debug("Check token: {}", token);
        if (null != token) {
            return LettuceUtil.exists(Values.TOKEN_KEY_PREFIX + token);
        } else {
            return false;
        }
    }
}
